function ASCIIToBase64 (data,ie){
    var keyMap = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
    var byte1, byte2, byte3;
    var char1,char2,char3,char4;
    var i = 0;
    var result = "";
    
    while (i < data.length){
        if (ie){
            byte1 = data[i++];
            if (i < data.length)
                byte2 = data[i++];
            else
                byte2= 0;
        
            if (i < data.length)
                byte3 = data[i++];
            else
                byte3= 0;
        }
        else{
            byte1 = data.charCodeAt(i++) & 0xff;
            if (i < data.length)
                byte2 = data.charCodeAt(i++)& 0xff;
            else
                byte2= 0;
        
            if (i < data.length)
                byte3 = data.charCodeAt(i++)& 0xff;
            else
                byte3= 0;
        }
        char1 = keyMap.charAt(byte1 >> 2);
        char2 = keyMap.charAt(((byte1 & 0x3)<<4) | (byte2>>4));
        char3 = keyMap.charAt((((byte2 & 0xF)<< 2) | (byte3 >>6 )));
        char4 = keyMap.charAt((byte3 & (0xF | (0x3 << 4))));
        
        if (i == data.length && data.length % 3 == 1){
            char3 = "=";
            char4 = "=";
        }
        
        if (i == data.length && data.length % 3 == 2){
            char4 = "=";
        }
        
        result += char1 + char2 + char3 + char4;
    }
    
    return result;
}

function urlToExt (path){
    var regex = /[A-Za-z0-9]*$/;
    var matches = path.match(regex);
    if (matches)
        return matches[0];
    
    return null;
}

function ImageLoader (loadingFrame){
    this.imagePaths = ["../pictures/base/cleanbg.jpg",
    "../pictures/base/mainmenu.jpg",
    "../pictures/base/menu.jpg",
    "../pictures/levels/levelCircuit/levelbg.jpg",
    "../pictures/levels/levelCircuit/manual.png",
    "../pictures/levels/levelCircuit/obv0.png",
    "../pictures/levels/levelCircuit/obv1.png",
    "../pictures/levels/levelCircuit/obv2.png",
    "../pictures/levels/levelCircuit/obv3.png",
    "../pictures/levels/levelCircuit/obv4.png",
    "../pictures/levels/levelCircuit/obv5.png",
    "../pictures/levels/levelCircuit/obv6.png",
    "../pictures/levels/levelCircuit/obv7.png",
    "../pictures/levels/levelCircuit/obv8.png",
    "../pictures/levels/levelElements/at/0.png",
    "../pictures/levels/levelElements/at/1.png",
    "../pictures/levels/levelElements/at/10.png",
    "../pictures/levels/levelElements/at/11.png",
    "../pictures/levels/levelElements/at/12.png",
    "../pictures/levels/levelElements/at/13.png",
    "../pictures/levels/levelElements/at/14.png",
    "../pictures/levels/levelElements/at/15.png",
    "../pictures/levels/levelElements/at/16.png",
    "../pictures/levels/levelElements/at/17.png",
    "../pictures/levels/levelElements/at/18.png",
    "../pictures/levels/levelElements/at/19.png",
    "../pictures/levels/levelElements/at/2.png",
    "../pictures/levels/levelElements/at/3.png",
    "../pictures/levels/levelElements/at/4.png",
    "../pictures/levels/levelElements/at/5.png",
    "../pictures/levels/levelElements/at/6.png",
    "../pictures/levels/levelElements/at/7.png",
    "../pictures/levels/levelElements/at/8.png",
    "../pictures/levels/levelElements/at/9.png",
    "../pictures/levels/levelElements/levelbg.jpg",
    "../pictures/levels/levelElements/manual.png",
    "../pictures/levels/levelElements/ob/0.jpg",
    "../pictures/levels/levelElements/ob/1.jpg",
    "../pictures/levels/levelElements/ob/10.jpg",
    "../pictures/levels/levelElements/ob/11.jpg",
    "../pictures/levels/levelElements/ob/12.jpg",
    "../pictures/levels/levelElements/ob/13.jpg",
    "../pictures/levels/levelElements/ob/14.jpg",
    "../pictures/levels/levelElements/ob/15.jpg",
    "../pictures/levels/levelElements/ob/16.jpg",
    "../pictures/levels/levelElements/ob/17.jpg",
    "../pictures/levels/levelElements/ob/18.jpg",
    "../pictures/levels/levelElements/ob/19.jpg",
    "../pictures/levels/levelElements/ob/2.jpg",
    "../pictures/levels/levelElements/ob/3.jpg",
    "../pictures/levels/levelElements/ob/4.jpg",
    "../pictures/levels/levelElements/ob/5.jpg",
    "../pictures/levels/levelElements/ob/6.jpg",
    "../pictures/levels/levelElements/ob/7.jpg",
    "../pictures/levels/levelElements/ob/8.jpg",
    "../pictures/levels/levelElements/ob/9.jpg",
    "../pictures/levels/levelFunctions/funct0.png",
    "../pictures/levels/levelFunctions/funct1.png",
    "../pictures/levels/levelFunctions/funct2.png",
    "../pictures/levels/levelFunctions/funct3.png",
    "../pictures/levels/levelFunctions/funct4.png",
    "../pictures/levels/levelFunctions/funct5.png",
    "../pictures/levels/levelFunctions/funct6.png",
    "../pictures/levels/levelFunctions/funct7.png",
    "../pictures/levels/levelFunctions/funct8.png",
    "../pictures/levels/levelFunctions/levelbg.jpg",
    "../pictures/levels/levelFunctions/manual.png",
    "../pictures/levels/levelJokes/levelbg.jpg",
    "../pictures/levels/levelLogic/blackCircle.png",
    "../pictures/levels/levelLogic/levelbg.jpg",
    "../pictures/levels/levelLogic/manual.png",
    "../pictures/levels/levelLogic/whiteCircle.png",
    "../pictures/levels/levelOptic/goal.png",
    "../pictures/levels/levelOptic/goalmask.png",
    "../pictures/levels/levelOptic/laser.png",
    "../pictures/levels/levelOptic/levelbg.jpg",
    "../pictures/levels/levelOptic/manual.png",
    "../pictures/levels/levelOptic/mirror.png",
    "../pictures/levels/levelPi/levelbg.jpg",
    "../pictures/levels/levelPi/manual.png",
    "../pictures/levels/levelPythagoras/levelbg.jpg",
    "../pictures/levels/levelPythagoras/manual.png",
    "../pictures/levels/levelPythagoras/pBall.png",
    "../pictures/levels/levelPythagoras/steel.jpg",
    "../pictures/levels/levelSort/levelbg.jpg",
    "../pictures/levels/levelSort/manual.png",
    "../pictures/levels/levelSort/sortButton.png",
    "../pictures/levels/levelSort/sortButtonClicked.png",
    "../pictures/levels/levelTurtle/levelbg.jpg",
    "../pictures/levels/levelTurtle/manual.png"];

    this.scriptPaths = [
    "../lib/prototype-1.6.0.2.js",
    "../js/box2d/common/b2Settings.js",
    "../js/box2d/common/math/b2Vec2.js",
    "../js/box2d/common/math/b2Mat22.js",
    "../js/box2d/common/math/b2Math.js",
    "../js/box2d/collision/b2AABB.js",
    "../js/box2d/collision/b2Bound.js",
    "../js/box2d/collision/b2BoundValues.js",
    "../js/box2d/collision/b2Pair.js",
    "../js/box2d/collision/b2PairCallback.js",
    "../js/box2d/collision/b2BufferedPair.js",
    "../js/box2d/collision/b2PairManager.js",
    "../js/box2d/collision/b2BroadPhase.js",
    "../js/box2d/collision/b2Collision.js",
    "../js/box2d/collision/Features.js",
    "../js/box2d/collision/b2ContactID.js",
    "../js/box2d/collision/b2ContactPoint.js",
    "../js/box2d/collision/b2Distance.js",
    "../js/box2d/collision/b2Manifold.js",
    "../js/box2d/collision/b2OBB.js",
    "../js/box2d/collision/b2Proxy.js",
    "../js/box2d/collision/ClipVertex.js",
    "../js/box2d/collision/shapes/b2Shape.js",
    "../js/box2d/collision/shapes/b2ShapeDef.js",
    "../js/box2d/collision/shapes/b2BoxDef.js",
    "../js/box2d/collision/shapes/b2CircleDef.js",
    "../js/box2d/collision/shapes/b2CircleShape.js",
    "../js/box2d/collision/shapes/b2MassData.js",
    "../js/box2d/collision/shapes/b2PolyDef.js",
    "../js/box2d/collision/shapes/b2PolyShape.js",
    "../js/box2d/dynamics/b2Body.js",
    "../js/box2d/dynamics/b2BodyDef.js",
    "../js/box2d/dynamics/b2CollisionFilter.js",
    "../js/box2d/dynamics/b2Island.js",
    "../js/box2d/dynamics/b2TimeStep.js",
    "../js/box2d/dynamics/contacts/b2ContactNode.js",
    "../js/box2d/dynamics/contacts/b2Contact.js",
    "../js/box2d/dynamics/contacts/b2ContactConstraint.js",
    "../js/box2d/dynamics/contacts/b2ContactConstraintPoint.js",
    "../js/box2d/dynamics/contacts/b2ContactRegister.js",
    "../js/box2d/dynamics/contacts/b2ContactSolver.js",
    "../js/box2d/dynamics/contacts/b2CircleContact.js",
    "../js/box2d/dynamics/contacts/b2Conservative.js",
    "../js/box2d/dynamics/contacts/b2NullContact.js",
    "../js/box2d/dynamics/contacts/b2PolyAndCircleContact.js",
    "../js/box2d/dynamics/contacts/b2PolyContact.js",
    "../js/box2d/dynamics/b2ContactManager.js",
    "../js/box2d/dynamics/b2World.js",
    "../js/box2d/dynamics/b2WorldListener.js",
    "../js/box2d/dynamics/joints/b2JointNode.js",
    "../js/box2d/dynamics/joints/b2Joint.js",
    "../js/box2d/dynamics/joints/b2JointDef.js",
    "../js/box2d/dynamics/joints/b2DistanceJoint.js",
    "../js/box2d/dynamics/joints/b2DistanceJointDef.js",
    "../js/box2d/dynamics/joints/b2Jacobian.js",
    "../js/box2d/dynamics/joints/b2GearJoint.js",
    "../js/box2d/dynamics/joints/b2GearJointDef.js",
    "../js/box2d/dynamics/joints/b2MouseJoint.js",
    "../js/box2d/dynamics/joints/b2MouseJointDef.js",
    "../js/box2d/dynamics/joints/b2PrismaticJoint.js",
    "../js/box2d/dynamics/joints/b2PrismaticJointDef.js",
    "../js/box2d/dynamics/joints/b2PulleyJoint.js",
    "../js/box2d/dynamics/joints/b2PulleyJointDef.js",
    "../js/box2d/dynamics/joints/b2RevoluteJoint.js",
    "../js/box2d/dynamics/joints/b2RevoluteJointDef.js",    
    "../base/score.js",
    "../base/timer.js",
    "../base/button.js",
    "../base/manual.js",
    "../base/pause.js",
    "../base/resultGraph.js",
    "../base/menu.js",
    "../base/levelMenu.js",
    "../base/mainmenu.js",
    "../base/nextlevelMenu.js",
    "../base/selectedLevelWin.js",
    "../base/level.js",
    "../levels/levelCircuit/playground.js",
    "../levels/levelCircuit/levelCircuit.js",
    "../levels/levelElements/levelElements.js",
    "../levels/levelFunctions/functions.js",
    "../levels/levelFunctions/functionslevel.js",
    "../levels/levelLogic/boolCircle.js",
    "../levels/levelLogic/logiclevel.js",
    "../levels/levelOptic/Geometry.js",
    "../levels/levelOptic/mirror.js",
    "../levels/levelOptic/levelReflect.js",
    "../levels/levelPi/unitCircle.js",
    "../levels/levelPi/levelPi.js",
    "../levels/levelPythagoras/box.js",
    "../levels/levelPythagoras/pythagoras.js",
    "../levels/levelSort/chlievik.js",
    "../levels/levelSort/levelSort.js",
    "../levels/levelTurtle/commands.js",
    "../levels/levelTurtle/turtle.js",
    "../levels/levelTurtle/turtlelevel.js",
    "../levels/levelJokes/jokes.js",
    "../levels/levelJokes/levelJokes.js",
    "../core/game.js"]

    this.loadedImages = new Array();
    this.loadedScripts = new Array();
    this.total = 0;
    this.totalBytes = 1923094;
    this.currentBytes = 0;
    this.update;
    this.loadingFrame = loadingFrame;
        
    this.LoadAll = function(){
        for (var i = 0; i < this.imagePaths.length;i++){
            this.LoadImage(this.imagePaths[i]);
        }
        for (var i = 0; i < this.scriptPaths.length;i++){
            this.loadScript(this.scriptPaths[i]);
        }
    }
        
    this.LoadImage = function (path){
        var obj = this;
        var image = new Image ();
        var prevSize = 0;
        var extension = urlToExt(path);
        
        extension = (extension == "jpg")?"jpeg":extension;
       
        var browerName = navigator.appName; 
        var request = new XMLHttpRequest();     
        if (browerName != "Microsoft Internet Explorer")
            request.overrideMimeType("plain/text; charset=x-user-defined");
        
        request.open ("GET",path,true);
        request.send(null);
        request.onreadystatechange = function (e){
            if (request.readyState == 4){
                var bytes;
                if (browerName != "Microsoft Internet Explorer"){
                    bytes = request.responseText;
                    if (request.status == 200){
                        image.src = "data:image/"+ extension + ";base64,"+ASCIIToBase64(bytes,false);
                        var reg = /picture{1}.*$/;
                        var index = path.match(reg);
                        obj.loadedImages[index] = image;
                    }
                }    
                else{
                    bytes = VBArray(request.responseBody).toArray();
                    if (request.status == 200){
                        image.src = "data:image/"+ extension + ";base64,"+ASCIIToBase64(bytes,true);
                        var reg = /picture{1}.*$/;
                        var index = path.match(reg);
                        obj.loadedImages[index] = image;
                    }
                }
            }
        }
        

        request.onprogress = function (e){
            if(e.lengthComputable) {
                obj.currentBytes += e.loaded - prevSize;
                prevSize = e.loaded;
                obj.loadingFrame.updateBar (obj.currentBytes/obj.totalBytes);
            }
        }
    }
    
    this.loadScript = function (path){
        var obj = this;
        var image = new Image ();
        var prevSize = 0;
        var script = document.createElement("script");
        var request = new XMLHttpRequest();     
        request.open ("GET",path,true);
        request.send(null);
        request.onreadystatechange = function (e){
            if (request.readyState == 4){
                var bytes;
                bytes = request.responseText;
                if (request.status == 200){
                    script.language = "javascript";
                    script.type = "text/javascript";
                    //                    script.defer = true;
                    script.text = bytes;
                    obj.loadedScripts[path] = script;
                }    
            }
        }
        
        
        var onErrorHandler = function() {
             console.log("daka chyba more");
        }

        request.addEventListener('error', onErrorHandler, false);
        
        request.onprogress = function (e){
            if(e.lengthComputable){
                obj.currentBytes += (e.loaded - prevSize);
                prevSize = e.loaded;
                obj.loadingFrame.updateBar (obj.currentBytes/obj.totalBytes);
            }
        }
    }
    
    this.addScripts = function (elementId){
        var scriptDiv = document.getElementsByTagName("head").item(0);
        for (var i = 0; i < this.scriptPaths.length;i++){
            scriptDiv.appendChild(this.loadedScripts[this.scriptPaths[i]]);
        }
    }
    
    this.isLoaded = function (){
        //console.log (this.total);
        if (this.currentBytes == this.totalBytes)
            return true;
        return false;
    }
    
}